﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using PriceLibrary.PriceService;

using VDataAdapter.Communication;
using VDataAdapter.EventManagement;
using VDataAdapter.QueueManagement;

namespace VDataAdapter.WorkerManagement
{
    class StockWorkerException : Exception
    {
        public StockWorkerException() : base() {}
        public StockWorkerException(string msg) : base(msg) {}
        public StockWorkerException(string msg, Exception inner) : base(msg, inner){}
    }

    class StockWorker : Worker
    {       
        IEventProviderQueue _eQueue;

        VDataCommunicator _comm;

        public StockWorker(string parentName,ManualResetEvent waitFirstTime, VDataCommunicator comm, IEventProviderQueue queue)
            : base(waitFirstTime, null, true) 
        {
            _comm = comm;
            _eQueue = queue;
            _name = parentName+"-StockWorker";
        }

        private bool _stopCheckingQueue;

        public bool StopCheckingQueue
        {
            get { return _stopCheckingQueue; }
            set { _stopCheckingQueue = value; }
        }

        override
        public void StopWork()
        {
            StopCheckingQueue = true;
        }

        /// <summary>
        /// Checking if there is event in Queue
        /// Will block until there is an FirstTimeEvent
        /// Can stop by setting StopCheckingQueue
        /// </summary>
        /// <returns></returns>
        private Top3PricesEvent CheckingEventQueue()
        {
            while (!_stopCheckingQueue)
            {
                try
                {
                    Top3PricesEvent e = _eQueue.GetTop3PricesEvent();

                    // sometimes a queue return null if the queue is empy
                    if (e == null)
                    {
                        Thread.Sleep(50);
                    }
                    else
                    {
                        return e;
                    }
                }
                catch (InvalidOperationException ex)
                {
                    if (ex.Message == "Queue empty")
                    {
                        // the queue is empty, just ignore it and try next time
                        Thread.Sleep(50);
                    }
                }
                catch (Exception ex)
                {
                    throw new StockWorkerException("Can get item from queue with unknown cause: " + ex.Message, ex);
                }
            }

            return null;
        }

        protected override void DoWork(object data)
        {
            try
            {
                Top3PricesEvent e = CheckingEventQueue();
                
                if (e != null)
                {
                    foreach (KeyValuePair<string, PriceLibrary.PriceService.StockBase> p in e.Top3Prices)
                    {
                        var infoDynamic =
                            (StockInfoDyns)p.Value;

                        _comm.SendStock(p.Key, infoDynamic);
                    }
                }
            }
            catch (InvalidCastException ex)
            {
                throw new StockWorkerException("Can not cast value: " + ex.Message, ex);
            }
            catch (Exception ex)
            {
                _status = "Error: " + ex.Message;
                throw new StockWorkerException("Error stock worker: " + ex.Message, ex);
            }
        }
    }
}
